package com.ai.service.made.impl;

import com.ai.common.constant.CommonArgs;
import com.ai.common.CommonResponse;
import com.ai.common.exception.ServiceException;
import com.ai.entity.alarm.TriggerAlarmParam;
import com.ai.entity.cameraFunctions.functions.CameraFunctionsPO;
import com.ai.entity.cameraFunctions.timeInterval.TimeIntervalBaseVO;
import com.ai.entity.function.FunctionPO;
import com.ai.entity.made.camera.*;
import com.ai.entity.server.ServerPO;
import com.ai.service.made.*;
import com.ai.util.HttpRequestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Service
public class AlgorithmCameraServiceImpl implements AlgorithmCameraService {

    @Resource
    CameraService cameraService;
    @Resource
    ServerService serverService;
    @Resource
    FunctionService functionService;

    @Resource
    CameraFunctionsService cameraFunctionsService;
    @Value("${api.live.url}")
    private String liveUrl;
    @Value("${api.ai.url}")
    private String aiUrl;
    @Resource
    private TimeIntervalService timeIntervalService;

    @Resource
    private RegionsService regionsService;


    /**
     * 打开摄像头
     *
     * @param cameraIdBO
     */
    @Override
    public CommonResponse onOpen(CameraIdBO cameraIdBO) {

        int state = 2;

//        摄像头什么时候有效--查看操作的摄像头是否存在
        CameraPO cameraPO = cameraService.getCameraOn(cameraIdBO);
        if (cameraPO == null) {
            return CommonResponse.error("请选择有效设备");
        }

        int id = cameraPO.getId();
//        根据摄像头的id和状态批量操作直播
        CommonResponse commonResponse = bulkSwitchForLive(id, state);
        //返回结果码：1成功，-1失败
        if (commonResponse.getCode() != 200) {
            return commonResponse;
        }
        cameraPO = new CameraPO();
        cameraPO.setState(1);
        cameraService.update(cameraPO, new QueryWrapper<CameraPO>().eq("id", id));
        CommonArgs.CAMERA_HEARTBEAT_MAP.put(id, System.currentTimeMillis());

        return CommonResponse.ok("开启成功");
    }

    /**
     * 关闭摄像头
     *
     * @param cameraIdBO
     */
    @Override
    public CommonResponse onClose(CameraIdBO cameraIdBO) {


        int state = 3;
//        CameraCheck cameraCheck = new CameraCheck();
////        鉴权
//        if (cameraCheck.isCurrentID(cameraIdBO.getCurrentId())) {
//            return cameraCheck.resultData;
//        }

        CameraPO cameraPO = cameraService.getCameraOn(cameraIdBO);
        if (cameraPO == null) {
            return CommonResponse.error("请选择有效设备");
        }

        int cameraId = cameraPO.getId();

        CommonResponse CommonResponse = bulkSwitchForLive(cameraId, state);
        if (CommonResponse.getCode() != 200) {
            return CommonResponse;
        }

        cameraPO.setState(2);
        cameraService.updateById(cameraPO);

        CommonArgs.CAMERA_HEARTBEAT_MAP.remove(cameraId);
        return CommonResponse.ok("关闭成功");
    }

    /**
     * 通过功能开关算法
     *
     * @param type
     * @param state
     */
    @Override
    public void bulkSwitchForTelegram(int type, int state, Integer delayTime) {
        bulkSwitchForTelegram(type, state, delayTime, null);
    }

    @Override
    public void bulkSwitchForTelegram(int type, int state, Integer delayTime, Map<String, Object> extendedProperties) {
        FunctionPO functionPO = functionService.getOne(new QueryWrapper<FunctionPO>().eq("type", type));
        List<SwitchCameraAlgorithmBO> switchCameraAlgorithmBOList = cameraFunctionsService.getCameraByType(functionPO, state, extendedProperties);

        for (SwitchCameraAlgorithmBO switchCameraAlgorithmBO : switchCameraAlgorithmBOList) {

            CameraPO cameraPO = cameraService.getById(switchCameraAlgorithmBO.getCameraId());
            int serverId = cameraPO.getServerId();
            if (serverId == 0) {
                throw new ServiceException("该摄像头未绑定服务器");
            }
            ServerPO server = serverService.getById(serverId);
            String ip = server.getIp();
            Integer port = server.getPort();
            if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || port == 0) {
                throw new ServiceException("该摄像头所绑定服务器未设置IP或端口");
            }
            String url = ("http://" + ip + ":" + port + "/") + aiUrl;


            new Thread(() -> {
                //延时开关
                if (delayTime != null && delayTime > 0) {
                    log.info("信号延迟【" + delayTime + "秒】启动");
                    try {
                        Thread.sleep(delayTime * 1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }

                String param = JSONObject.toJSONString(switchCameraAlgorithmBO);
                log.info("启停算法的指令为： " + param);

                String s = HttpRequestUtil.sendPost(url, param);

                if (StringUtils.isEmpty(s) || "null".equals(s)) {
                    log.info("网络请求失败！");
                    return;
                }
                JSONObject o = JSONObject.parseObject(s);
                int resultCode = Integer.valueOf(o.getString("result_code"));
                log.info("摄像头操作" + ((resultCode == -1) ? "失败" : "成功"));
            }).start();
        }
    }

    @Override
    public CommonResponse detectionStart() {

        String url = "http://192.168.8.153:5000/predict";

//        String param = JSONObject.toJSONString(message);

        String param ="{\n" +
                "    \"cameraCode\":\"code\",\n" +
                "    \"cameraId\":1133,\n" +
                "    \"detectionTimes\":0,\n" +
                "    \"functions\":[\n" +
                "        {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1101\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1102\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1103\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1104\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1105\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1105\n" +
                "        }\n" +
                "    ],\n" +
                "    \"ip\":\"192.168.8.153\",\n" +
                "    \"password\":\"123123\",\n" +
                "    \"planNo\":\"1234\",\n" +
                "    \"status\":4,\n" +
                "    \"streamWay\":1,\n" +
                "    \"url\":\"/home/server/cfc/video_file/bgs/phone_bgs/louxia1.mp4\",\n" +
                "    \"username\":\"camera_account\"\n" +
                "}";
        String s = HttpRequestUtil.sendPost(url, param);

        if (StringUtils.isEmpty(s) || "null".equals(s)) {
            log.info("网络请求失败！");
            return null;
        }

        JSONObject o = JSONObject.parseObject(s);
        int resultCode = Integer.valueOf(o.getString("resultCode"));
        log.info("摄像头操作" + ((resultCode == -1) ? "失败" : "成功"));

        return CommonResponse.ok("功能开启成功");
    }

    /**
     * 模拟触发算法
     * 开启算法传 1 4
     * 关闭算法传2 5
     * @param
     * @return 状态 2开启直播 3关闭直播 4开始算法 5关闭算法
     */
    @Override
    public CommonResponse triggerAlarm(TriggerAlarmParam triggerAlarmParam) {
        String alarmType=triggerAlarmParam.getAlarmType();
        Integer functionType=triggerAlarmParam.getFunctionType();
        String planNo =triggerAlarmParam.getPlanNo();
        String doorNum =triggerAlarmParam.getDoorNum();
        Integer state =triggerAlarmParam.getState();
        Integer status =triggerAlarmParam.getStatus();
        List<CameraPO> cameraList = new ArrayList<>();
        ArrayList<Integer> funTypeList = new ArrayList<>();
        funTypeList.add(functionType);
        cameraList = cameraFunctionsService.getCameraSteelList(funTypeList);

        if (CollectionUtils.isEmpty(cameraList)){
            return CommonResponse.ok();
        }
        cameraList.forEach(item->{
            if (null==item){
                return;
            }
            log.info("===========================  手动触发  ---准备算法接口入参 ===========================");
            //基本参数
            log.info("===========================  摄像头信息：{}  ===========================",JSONObject.toJSONString(item));
            SwitchCameraAlgorithmBO switchCameraAlgorithmBO = new SwitchCameraAlgorithmBO();
            switchCameraAlgorithmBO.setCameraId(item.getId());
            switchCameraAlgorithmBO.setUsername(item.getUsername());
            switchCameraAlgorithmBO.setPassword(item.getPassword());
            switchCameraAlgorithmBO.setIp(item.getIp());
            switchCameraAlgorithmBO.setUrl(item.getUrl());
            switchCameraAlgorithmBO.setCameraCode(item.getCode());
            switchCameraAlgorithmBO.setPlanNo(planNo);//板坯号
            switchCameraAlgorithmBO.setPort(item.getPort());
            switchCameraAlgorithmBO.setStreamWay(item.getStreamWay());
            //触发类型 默认0首次触发 1校验触发  默认为0
            switchCameraAlgorithmBO.setDetectionTimes(0);
            if (doorNum != null){
                switchCameraAlgorithmBO.setDoorNum(doorNum);
            }
            //开启算法或者关闭算法

            switchCameraAlgorithmBO.setState(state);//开启算法
            switchCameraAlgorithmBO.setStatus(status);

            //功能参数
            ArrayList<SwitchCameraFunctionAlgorithmBO> switchCameraFunctionAlgorithmBOS = new ArrayList<>();
            ArrayList<SwitchCameraFunctionAlgorithmBO> listSTACKINGBOS = new ArrayList<>();
            ArrayList<SwitchCameraFunctionAlgorithmBO> list1104BOS = new ArrayList<>();
            for (Integer funType : funTypeList) {
                FunctionPO functionPO = functionService.getOne(new QueryWrapper<FunctionPO>()
                        .eq("type", funType));
                Integer cameraId = item.getId();
                Integer funId = functionPO.getId();
                CameraFunctionsPO cameraFunctionsPO = cameraFunctionsService.getOne(new QueryWrapper<CameraFunctionsPO>()
                        .eq("camera_id", cameraId).eq("function_id", funId));

                SwitchCameraFunctionAlgorithmBO switchCameraFunctionAlgorithmBO = new SwitchCameraFunctionAlgorithmBO();
                switchCameraFunctionAlgorithmBO.setId(cameraFunctionsPO.getId());//id
                switchCameraFunctionAlgorithmBO.setCode(functionPO.getCode());//code
                switchCameraFunctionAlgorithmBO.setType(funType.toString());//功能代码
                switchCameraFunctionAlgorithmBO.setThreshold(cameraFunctionsPO.getThreshold());//算法阈值

                //画框区域点集合
                List<SwithCameraFunctionRegionsAlgorithmBO> spots = regionsService.getSpots(cameraFunctionsPO.getId());
                switchCameraFunctionAlgorithmBO.setSpots(spots);
                //开启关闭时间
                List<TimeIntervalBaseVO> timeIntervalList = timeIntervalService.getTimeIntervalList(cameraFunctionsPO.getCameraId());
                switchCameraFunctionAlgorithmBO.setTimeIntervals(timeIntervalList);
                list1104BOS.add(switchCameraFunctionAlgorithmBO);
            }

            switchCameraAlgorithmBO.setFunctions(list1104BOS);
            int serverId = item.getServerId();
            if (serverId == 0) {
                throw new ServiceException("该摄像头未绑定服务器");
            }
            ServerPO server = serverService.getById(serverId);
            String ip = server.getIp();
            Integer port = server.getPort();
            if (org.apache.commons.lang3.StringUtils.isBlank(ip) || port == null || port == 0) {
                throw new ServiceException("该摄像头所绑定服务器未设置IP或端口");
            }

            String url = ("http://" + ip + ":" + port + "/") + aiUrl;
            log.info("------------------------- 请求url：{} --------------------------",url);

//                Integer stackingID = new Random().nextInt(900000)+100000;
            Integer stackingID = 1731733;
                switchCameraAlgorithmBO.setTaskId(stackingID);
//                saveSignalCameraRelation(item.getCode(),item.getId(),stackingID);//保存信号与摄像头之间的关系

                    new Thread(()-> {

                        String param = JSONObject.toJSONString(switchCameraAlgorithmBO);
                        log.info("------------------------- 启停算法的指令为：{} --------------------------", param);
                        String s = HttpRequestUtil.sendPost(url, param);
                        log.info("------------------------- 请求url：{} --------------------------", url);

                        if (StringUtils.isEmpty(s) || "null".equals(s)) {
                            log.info("------------------------- 网络请求失败！ --------------------------");

                            return;
                        }

                        JSONObject o = JSONObject.parseObject(s);
                        int resultCode = Integer.parseInt(o.getString("resultCode"));
                        log.info("===========================  算法返回结果：{}   ===========================",JSONObject.toJSONString(o));
                        log.info("摄像头操作" + ((resultCode == -1) ? "失败" : "成功"));
//                requestAlgorithm(switchCameraAlgorithmBO,url, finalHasStopSignal,telId,stackingSignalRecord, stackPlcCode);
                    }).start();
        });


        return CommonResponse.ok();
    }


    /**
     * 直播开关
     *
     * @param cameraId
     * @param state    2、3对应开启直播、关闭直播
     * @return
     */
    private CommonResponse bulkSwitchForLive(int cameraId, int state) {
        CameraPO cameraPO = cameraService.getById(cameraId);
        //服务器id
        int serverId = cameraPO.getServerId();
        if (serverId == 0) {
            return CommonResponse.error("该摄像头未绑定服务器");
        }
//        通过服务器ip获取对应的服务器
        ServerPO server = serverService.getById(serverId);
        if (null == server){
            return CommonResponse.error("服务器不存在，请检查摄像头后重新操作");
        }
        String ip = server.getIp();
        Integer port = server.getPort();
        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || port == 0) {
            return CommonResponse.error("该摄像头所绑定服务器未设置IP或端口");
        }
        String url = ("http://" + ip + ":" + port + "/") + liveUrl;

        String param;
//        摄像头与算法实体
        CameraSwitchAlgorithmBO algorithmBO = new CameraSwitchAlgorithmBO();
        if (state == 3) {
            //关闭直播
            algorithmBO.setCameraId(cameraId);
            algorithmBO.setState(3);
            algorithmBO.setUrl("");
            algorithmBO.setCameraCode(cameraPO.getCode());
            algorithmBO.setStatus(3);
            param = JSONObject.toJSONString(algorithmBO);

            log.info("------[" + cameraPO.getCode() + "]关闭直播");

        } else {
            //打开直播
            SwitchCameraAlgorithmBO switchCameraAlgorithmBO = new SwitchCameraAlgorithmBO();
            BeanUtils.copyProperties(cameraPO, switchCameraAlgorithmBO);
            switchCameraAlgorithmBO.setCameraId(cameraId);
            switchCameraAlgorithmBO.setCameraCode(cameraPO.getCode());
            log.info("------[" + cameraPO.getCode() + "]开启直播");

            switchCameraAlgorithmBO.setState(state);
            switchCameraAlgorithmBO.setStatus(state);
            param = JSONObject.toJSONString(switchCameraAlgorithmBO);
        }

        String sr = HttpRequestUtil.sendPost(url, param);

        if (StringUtils.isEmpty(sr) || "null".equals(sr)) {//会返会null字符串么
            return CommonResponse.error("网络请求失败！");
        }
        //解析算法返回数据
        JSONObject jsonObject = JSONObject.parseObject(sr);
        //返回结果码：1成功，-1失败
        int result = Integer. valueOf(jsonObject.getString("resultCode"));
        String msg = jsonObject.getString("resultMsg");
        if (result == -1) {
            return CommonResponse.error("摄像头操作失败：" + msg);
        }
        return CommonResponse.ok("操作成功");
    }
}
